package com.ruoyi.aitcommon.utils;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.aitcommon.vo.AggMap;
import com.ruoyi.common.core.redis.RedisCache;

import cn.hutool.core.util.StrUtil;

@Component
public class EntityCache {
	@Autowired
	RedisCache redisCache;
	
	public String prefix="EntityCache:";
	
	/**
	 * 从entityinfo中构造redis缓存key
	 * @param datamap entityinfo翻译后的数据
	 * @return key redis key
	 * @throws Exception
	 */
	private String getKey(Map<String,Object> datamap) throws Exception {
		String type=StrUtil.toString(datamap.get("type"));
		ExceptionUtils.checkBlankOrUndefined(type, "获取type为空:"+StrUtil.toString(datamap));
		String code=StrUtil.toString(datamap.get("code"));
		if(StrUtil.isBlank(code)) {
			LogUtils.warn("获取code为空!请检查EntityInfo中的Code设置!");
			return "";
		}
		//ExceptionUtils.checkBlankOrUndefined(code, "获取code为空:"+StrUtil.toString(code));
		String name=StrUtil.toString(datamap.get("name"));
//		key=类型:编码_名称
		String key=type+":"+code+"_"+name;
		return prefix+key;
	}

	/**
	 * 从data中获取code,name,type的值,并赋值给entityinfo对象
	 * @param entityInfo
	 * @param data
	 * @return
	 * @throws Exception
	 */
	private String getKey(Map<String,Object> entityInfo,Map<String,Object> data) throws Exception {
//		利用data,翻译entityInfo中的变量
		Map<String,Object> entityMap=FlowParamUtils.getFlowParamsValue(entityInfo, data);
		return this.getKey(entityMap);
	}
	/**
	 * entityInfo同缓存比较
	 * @param entityInfo 实体信息
	 * @param data 相关数据
	 * @return 0-存在且相同 非0-不存在或不相同
	 * @throws Exception
	 */
	public boolean compareEntityCache(Map<String,Object> entityInfo,JSONObject data) throws Exception {
		String key=this.getKey(entityInfo, data);
		ObjUtils.checkBlank(key,"缓存对比,获取的Key为空.entityInfo配置:[%s]",entityInfo.toString());

		String oldstr = redisCache.getCacheObject(key);
//		这里转为String,是为了不丢失null值
		String datastr=StrUtil.toString(data);
		int ret=StrUtil.compare(datastr, oldstr, false);
		if(ret==0)
			return true;
		else
			return false;
	}
	
	/**
	 * 设置数据缓存至Redis
	 * @param entityInfo 数据映射关系
	 * @param data 数据
	 * @throws Exception
	 */
	public void setEntityCache(Map<String,Object> entityInfo,JSONObject data) throws Exception {
		String key=this.getKey(entityInfo, data);
//		这里转为String,是为了不丢失null值
		redisCache.setCacheObject(key, StrUtil.toString(data));
	}
	
	public boolean hasEntityCache(Map<String,Object> entityInfo,JSONObject data) throws Exception{
		String key=this.getKey(entityInfo, data);
		if(StrUtil.isBlank(key))
			return false;
		
//		依据key值获取缓存中的数据
		String oldstr = redisCache.getCacheObject(key);
		if(StrUtil.isBlank(oldstr))
			return false;
		else
			return true;
	}
	
	/**
	 * 将当前数据同缓存数据对比,相同的数据过滤掉
	 * @param entityInfo 实体信息
	 * @param datas 数据集合
	 * @return 不相同的数据,包含新增和修改
	 * @throws Exception
	 */
	public List<Map<String,Object>> filterEntityChange(Map<String,Object>entityInfo , List<Map<String,Object>> datas) throws Exception{
		if(datas==null)
			throw new Exception("传入datas为空!");

		String oldkey="~!@";
		List<Map<String, Object>> retlist = ListMapUtils.newListMap();
		for(Map<String,Object> data:datas) {
			JSONObject dataJson=new JSONObject(data);
			final String newkey = this.getKey(entityInfo, data);
			if(oldkey.equals(newkey)){
//				两条数据的key相同
				LogUtils.warn("依据entityInfo获取Key相同,检查entityInfo配置或存在重复数据");
			}
//			dataJson通redis缓存对比
			boolean flag = this.compareEntityCache(entityInfo, dataJson);
			oldkey=newkey;
//			如果相同,跳过该记录
			if(flag==true) {
				continue;
			}
//			如果不同,添加到返回集合中
			retlist.add(data);
		}
		LogUtils.info("缓存日志:相同条数[{}]条,不同条数[{}]条", datas.size()-retlist.size(),retlist.size());
		FlowUtils.addBulletin("缓存:相同条数[{}]条,不同条数[{}]条", datas.size()-retlist.size(),retlist.size());
		if(datas.size()>AITConst.WARN_QUERY_NUM){
			LogUtils.perfWarn("缓存过滤前 数据超过{}条",AITConst.WARN_QUERY_NUM);
		}
		if(retlist.size()>AITConst.WARN_UPDATE_NUM){
			LogUtils.perfWarn("缓存过滤后 有效数据超过{}条",AITConst.WARN_UPDATE_NUM);
		}
		return retlist;
	}
	
	public List<AggMap> filterAggChange(Map<String,Object>entityInfo , List<AggMap> datas) throws Exception{
		List<Map<String,Object>> list = ListMapUtils.agg2Map(datas);
		List<Map<String, Object>> flist = filterEntityChange(entityInfo,list);
		return ListMapUtils.map2Agg(flist);
	}
	
	/**
	 * 将当前数据同缓存数据对比,已经存在的数据过滤掉
	 * @param entityInfo 实体信息
	 * @param datas 数据集合
	 * @return 缓存中不存在的数据
	 * @throws Exception
	 */
	public List<Map<String,Object>> filterEntityHas(Map<String,Object>entityInfo , List<Map<String,Object>> datas) throws Exception{
		List<Map<String, Object>> retlist = ListMapUtils.newListMap();

		String oldkey="~!@";
		for(Map<String,Object> data:datas) {
			JSONObject dataJSON=new JSONObject(data);
			final String newkey = this.getKey(entityInfo, data);
			if(oldkey.equals(newkey)){
//				两条数据的key相同
				LogUtils.warn("依据entityInfo获取Key相同,检查entityInfo配置或存在重复数据");
			}
			final boolean flag = this.hasEntityCache(entityInfo, dataJSON);
			oldkey=newkey;
//			数据存在,直接跳过
			if(flag==true) {
				continue;
			}
//			数据不存在,添加到返回列表中
			retlist.add(data);
		}
		LogUtils.info("缓存日志:存在条数[{}]条,不存在条数[{}]条", datas.size()-retlist.size(),retlist.size());
		FlowUtils.addBulletin("缓存:存在条数[{}]条,不存在条数[{}]条", datas.size()-retlist.size(),retlist.size());
		return retlist;
	}
}
